﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;

namespace BrasilFramework.Controle.Silverlight
{
    public class JanelaModal
    {
       
        #region Classe interna JanelaModalBase

        private class JanelaModalBase : UserControl
        {
            private readonly Grid areaPai;
            private readonly Canvas fundo;

            internal JanelaModalBase(Grid area, UserControl conteudo)
            {
                areaPai = area;
                Conteudo = conteudo;

                fundo = new Canvas
                            {
                                Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0))
                            };

                fundo.Children.Clear();
                fundo.Children.Add(Conteudo);

                Content = fundo;

                Application.Current.Host.Content.Resized += OnJanelaModalBaseResized;

                Loaded += OnJanelaModalBaseLoaded;
            }

            public UserControl Conteudo { get; private set; }

            internal void Fechar()
            {
                Application.Current.Host.Content.Resized -= OnJanelaModalBaseResized;
                Loaded -= OnJanelaModalBaseLoaded;

                Conteudo.MouseLeftButtonDown -= OnMouseLeftButtonDown;
                Conteudo.MouseLeftButtonUp -= OnMouseLeftButtonUp;
                Conteudo.MouseMove -= OnMouseMove;

                fundo.Children.Clear();
            }

            #region Eventos

            #region Comum

            private void OnJanelaModalBaseLoaded(object sender, RoutedEventArgs e)
            {
                Conteudo.MouseLeftButtonDown += OnMouseLeftButtonDown;
                Conteudo.MouseLeftButtonUp += OnMouseLeftButtonUp;
                Conteudo.MouseMove += OnMouseMove;

                Conteudo.Focus();
                Conteudo.TabNavigation = KeyboardNavigationMode.Cycle;

                fundo.Width = areaPai.ActualWidth;
                fundo.Height = areaPai.ActualHeight;

                OnJanelaModalBaseResized(null, EventArgs.Empty);
            }

            private void OnJanelaModalBaseResized(object sender, EventArgs e)
            {
                if (Conteudo != null && !double.IsNaN(Conteudo.Width) && !double.IsNaN(areaPai.ActualWidth))
                    Conteudo.SetValue(Canvas.LeftProperty, (areaPai.ActualWidth - Conteudo.Width) / 2);

                if (Conteudo != null && !double.IsNaN(Conteudo.Height) && !double.IsNaN(areaPai.ActualHeight))
                    Conteudo.SetValue(Canvas.TopProperty, (areaPai.ActualHeight - Conteudo.Height) / 2);
            }

            public void AtualizarPosicao()
            {
                OnJanelaModalBaseResized(null, EventArgs.Empty);
            }

            #endregion

            #region Arrastar e Soltar

            private bool capturandoMouse;
            private Point ultimaPosicaoMouse;

            private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                capturandoMouse = Conteudo.CaptureMouse();
                ultimaPosicaoMouse = e.GetPosition(null);
            }

            private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                if (!capturandoMouse) return;

                Conteudo.ReleaseMouseCapture();
                ultimaPosicaoMouse = new Point();
                capturandoMouse = false;
            }

            private void OnMouseMove(object sender, MouseEventArgs e)
            {
                if (capturandoMouse == false)
                    return;

                Point posicaoArea = e.GetPosition(Area);
                Point posicaoMouse = e.GetPosition(null);

                double posicaoXArea = Math.Abs(posicaoMouse.X - posicaoArea.X);
                double posicaoYArea = Math.Abs(posicaoMouse.Y - posicaoArea.Y);

                double dblX = (double)Conteudo.GetValue(Canvas.LeftProperty)
                              + posicaoMouse.X - ultimaPosicaoMouse.X;

                double dblY = (double)Conteudo.GetValue(Canvas.TopProperty)
                              + posicaoMouse.Y - ultimaPosicaoMouse.Y;

                if (dblX > -posicaoXArea && dblX + Conteudo.ActualWidth < areaPai.ActualWidth + posicaoXArea)
                    Conteudo.SetValue(Canvas.LeftProperty, dblX);

                if (dblY > -posicaoYArea && dblY + Conteudo.ActualHeight < areaPai.ActualHeight + posicaoYArea)
                    Conteudo.SetValue(Canvas.TopProperty, dblY);

                ultimaPosicaoMouse = posicaoMouse;
            }

            #endregion

            #endregion
        }

        #endregion

        #region Métodos públicos da janela

        private static Grid area;

        private readonly Canvas fundo = new Canvas();
        private readonly Popup janelaFundo = new Popup();
        private Popup janela;
        private JanelaModalBase janelaConteudo;

        /// <summary>
        /// Deve ser configurar no início da aplicação
        /// </summary>
        public static Grid Area
        {
            get { return area; }
            set { area = value; }
        }

        public void Abrir(UserControl controle)
        {
            fundo.Background = new SolidColorBrush(Color.FromArgb(70, 0, 0, 0));
            janelaFundo.Child = fundo;
            OnHostResized(null, EventArgs.Empty);
            janelaFundo.IsOpen = true;

            Application.Current.Host.Content.Resized += OnHostResized;

            janelaConteudo = new JanelaModalBase(area, controle);
            janela = new Popup { Child = janelaConteudo };

            if (area != null)
                area.Children.Insert(0, janela);

            janela.IsOpen = true;
        }

        public UserControl Fechar()
        {
            UserControl oRet = null;

            if (janela != null)
            {
                janela.IsOpen = false;

                if (area != null)
                    area.Children.Remove(janela);

                var oBase = janela.Child as JanelaModalBase;

                if (oBase != null)
                {
                    oRet = oBase.Conteudo;
                    oBase.Fechar();
                }

                janela.Child = null;
                janela = null;
            }

            if (janelaFundo != null)
            {
                janelaFundo.IsOpen = false;
            }

            return oRet;
        }

        #endregion

        #region Eventos da Janela

        protected void OnHostResized(object sender, EventArgs e)
        {
            fundo.Width = Application.Current.Host.Content.ActualWidth;
            fundo.Height = Application.Current.Host.Content.ActualHeight;
        }

        public void AtualizarPosicao()
        {
            janelaConteudo.AtualizarPosicao();
        }

        #endregion

    }
}